from flask import Flask
from flask_session import Session
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import CSRFProtect, csrf
from redis import StrictRedis
import pymysql


pymysql.install_as_MySQLdb()

# from config import Config
from config import configs

import logging
from logging.handlers import RotatingFileHandler

# 创建一个空的db对象
db = SQLAlchemy()

# 准备空的redis_store
# 以下代码让redis_store在其他地方也有类型和提示
redis_store = None  # type: StrictRedis


def setup_log(level):
    # 设置日志的记录等级

    logging.basicConfig(level=level) # 调试debug级
    # 创建日志记录器器，指明⽇志保存的路径、每个⽇日志⽂文件的最⼤大⼤大⼩小、保存的⽇日志⽂文件个数上限
    file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024*1024*100, backupCount=10)
    # 创建日志记录的格式 ⽇志等级 输⼊入⽇日志信息的⽂文件名 ⾏行行数 ⽇日志信息
    formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
    # 为刚创建的日志记录器设置⽇志记录格式
    file_log_handler.setFormatter(formatter)
    # 为全局的⽇日志⼯工具对象(flask app使⽤用的)添加⽇志记录器器
    logging.getLogger().addHandler(file_log_handler)


# 创建app的工厂方法
def create_app(config_name):

    # 读取配置类
    config_class = configs[config_name]

    # 调⽤用设置⽇日志等级的函数:根据环境的不同，选择不同的日志等级
    setup_log(configs[config_name].LOGGING_LEVEL)

    # 创建app实例
    app = Flask(__name__)

    # 2.2加载app的配置
    app.config.from_object(config_class)

    # 3.3创建连接到mysql数据库的对象
    # db = SQLAlchemy(app)
    db.init_app(app)

    # 4.1redis数据库配置
    global redis_store
    redis_store = StrictRedis(host=config_class.REDIS_HOST, port=config_class.REDIS_PORT, decode_responses=True)

    # 5开启CSRF保护,进行初始化并关联app
    # 什么情况下才代表保护成功:如果用户发送 POST，DELETE, PUT, ...时，没有携带csrf_token或者错误，服务器返回状态码400/403
    CSRFProtect(app)

    # 6使⽤flask_session扩展存储session到Redis数据库
    Session(app)

    # 注册index蓝图
    from info.modules.index import index_blue
    app.register_blueprint(index_blue)

    # 注册passport蓝图
    from info.modules.passport import passport_blue
    app.register_blueprint(passport_blue)

    # 注册news蓝图
    from info.modules.news import news_blue
    app.register_blueprint(news_blue)

    # 注册user蓝图
    from info.modules.user import user_blue
    app.register_blueprint(user_blue)

    # 注册admin蓝图
    from info.modules.admin import admin_blue
    app.register_blueprint(admin_blue)

    # 添加自定义的过滤器到模版过滤器列表
    from info.utils.comment import do_rank
    app.add_template_filter(do_rank, 'rank')

    # 给每一个响应中，都写入一个cookie,值为csrf_token
    @app.after_request
    def after_request_set_csrf_token(response):
        # 生成csrf_tokende 的值
        csrf_token = csrf.generate_csrf()
        # 将csrf_token写入到cookie
        response.set_cookie('csrf_token', csrf_token)
        return response

    # 返回工厂方法的成品：读取了指定配置的app
    return app